#include "php_dl.h"
#include "zend_extensions.h"


static HashTable libraries;

zend_bool load_dynamic_library(char* dlpath) {
	if (!zend_hash_exists(&libraries, dlpath, strlen(dlpath))) {
		DL_HANDLE handle = DL_LOAD(dlpath);

		if (!handle) {
			return FAILURE;
		}
		return zend_hash_add(&libraries, dlpath, strlen(dlpath), handle, sizeof(handle), NULL);

	}

	return SUCCESS;
}

zend_bool unload_dynamic_library(char *dlpath) {
	DL_HANDLE handle = NULL;

	if (zend_hash_find(&libraries, dlpath, strlen(dlpath), &handle)) {
		if(!DL_UNLOAD(handle)) {
			return FAILURE;
		}

		return zend_hash_del(&libraries, dlpath, strlen(dlpath));
	}

	return 0;
}

void* load_native_function(DL_HANDLE handle, char* fname) {
	return DL_FETCH_SYMBOL(handle, fname);
}

void* load_native_function_from(char *dlpath, char* fname) {
	DL_HANDLE handle = NULL;

	if (zend_hash_find(&libraries, dlpath, strlen(dlpath), &handle)) {
		return load_native_function(handle, fname);
	}

	return NULL;
}

/*void call_native_function(void* fn, void**params, int params_length, void* ret) {
	ret = ((php_native_function) fn)(params);


}*/

void copy_references(zval* array, void** to, int n) {

	int i = 0;
	HashTable *ht = Z_ARRVAL_P(array);

	foreach(param, ht)
		switch (Z_TYPE_P(param)) {
			case IS_LONG:
			case IS_BOOL:	to[i] = &Z_LVAL_P(param);	break;
			case IS_DOUBLE:	to[i] = &Z_DVAL_P(param);	break;
			case IS_STRING:	to[i] = Z_STRVAL_P(param);	break;
			default:		to[i] = NULL;				break;
		}
		i++;
	endforeach();
}

void unload_all_loaded_libraries() {
	DL_HANDLE handle = NULL;

	foreach(library, &libraries)
		zend_hash_get_current_data(&libraries, handle);
		if(handle) {
			DL_UNLOAD(handle);
		}
	endforeach();
}
